

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>


//asmlinkage int shell(int timeLimit);

//Handlers
//void alarmHandler(int sig);
//void sigHandler(int sig);
void Handler(int sig);
//Print messages
void printKillMessage();
void printEscapeMessage();

//int myAtoi(char* c);

//variables
pid_t pid;
char *arg[] = {"", NULL};//arrays for execve
char *env[] = {"",NULL};//empty arrays for execve
int isKilled=0;//bool var to ensure correct kill on interrupt
int error;
int bytesRead=0;
/*******************************
 *Alarm handler kills the child
 * when alarm signal is found.
 * If kill fails,
 * reports error and exits
 ********************************/
/*void alarmHandler(int sig)
{
	if(sig==SIGALRM)
	{
		if(-1==kill(pid, SIGKILL)) //attempt a kill
		{
			perror("kill failed");	   //if failed, print message
			exit(1);	   //and quit
		}
		else
		{	
			isKilled=1;	 //set killflag
			printKillMessage(); //print out kill message
		}
	}//end if
}//end alarmHandler
*/
/*******************************
 *Interrupt handler kills the child
 * when int signal is found. If no child
 * is running, parent is killed.
 ********************************/
/*
void intHandler(int sig)
{
	if(sig==SIGINT)
	{
		int returnVal=kill(pid, SIGKILL); //try to kill child
		if(-1==returnVal)//if the child was not killed
			if(-1==kill(getpid(),SIGKILL))	//kill parent	
			{
				perror("Kill parent"); //if unsuccessful
				exit(1);		//exit
			}
		alarm(0); //cancel alarm
	}//end if
}//end intHandler


*/
void Handler(int sig)
{
	if(sig==SIGINT){// press ctrl+c to signal this interupt. 
		if(-1==kill(pid, SIGKILL))
		{
			perror("kill failed");

		}
		alarm(0);
		exit(0);
	}
	else if(sig==SIGALRM)
	{
		if(-1==kill(pid, SIGKILL)) //attempt a kill
		{
			perror("kill failed");	   //if failed, print message
			exit(1);	   //and quit
		}
		else
		{	
			isKilled=1;	 //set killflag
			printKillMessage(); //print out kill message
		}
	}//end if
}





/*******************************
 *The shell takes in the time limit 
 * as an argument
 ********************************/
asmlinkage int sys_myshell(int timeLimit)
{
	char cmd[1024];//get the initial user input
	int bytesRead;	//actual number of characters read in by read()
	int status;	//for the wait command

	while(1)
	{
		isKilled=0;		
		//		signal(SIGINT,intHandler);
		signal(SIGINT,Handler);
		if(-1==write(1,"#Your command>",14))	//print out prompt
		{perror("Write failed"); exit(1);} //check for error

		if((bytesRead=read(0,cmd,1024))<0) //get the size of the input
		{perror("Read failed"); exit(1);} //check for errors

		int i;
		for(i=0; i<1024; ++i)   //loop through to take out args
		{
			if('\0'==cmd[i])   //if we are at a null, break out
				break;
			if(' '==cmd[i])   //if we are at a space, make it a null.
				cmd[i]='\0';
		}
		cmd[bytesRead-1]='\0';	//set last char to null

		if(-1==(pid=fork()))		//create a child process
		{perror("fork failed"); exit(1);} //error check

		signal(SIGALRM,Handler);	//set up alarm handler
	//	signal(SIGALRM,alarmHandler);	//set up alarm handler
		alarm(timeLimit);//set alarm to go off at timeLimit

		//if we are in the child process
		if(!pid){
			if(-1==execve(cmd,arg,env) )	//exec the command
			{perror("execve failed"); exit(1);} //error check
		}
		else	//if we are in the parent
		{
			if(-1==wait(&status)) //wait
			{perror("wait failed");exit(1);}

			if(!isKilled) //if no child was killed
				printEscapeMessage();
			alarm(0);	//cancel alarm
		}

	}//end while
}//end shell

/*
 *Prints out the kill message
 */
void printKillMessage()
{
	if(-1==write(1,"\nTimeout, kill the process.\n",29))
	{perror("write failed"); exit(1);}

}

/*
 *Prints out the escape message
 */
void printEscapeMessage()
{
	if(-1==write(1,"\nSuccessful kill the process.\n",30))
	{perror("Write failedxo"); exit(1);}//error check

}

/*******************************
 *Main parses the arguments and
 * calls the shell
 ********************************/
/*
int main(int argc, char* argv[])
{
	int timeLimit;
	if(argc<2) //if no args are entered
	{
		if(-1==write(1,"Please enter an argument.\n",26))
		{perror("write failedxxx:");exit(1); }
		exit(1);	//exit if no args
	}
	//	timeLimit = myAtoi(argv[1]);//get the time limit from the args
	timeLimit = atoi(argv[1]);//get the time limit from the args
	if(timeLimit<=0)
	{
		if(-1==write(1,"Argument must be positive.\n",27))
		{perror("write failed"); exit(1); }
		exit(1);	//exit if args are negative
	}
	shell(timeLimit);	//call the shell with user input
}


*/


//int myAtoi2()


// int myAtoi(char* c)
// {
// 	int num=0;
// 	for(int i=0; c[i]!='\0';++i)
// 	{
// 		if(i>10)
// 		{
// 			if(-1==write(1,"atoi failed: too large\n",25))
// 				perror("write failed");exit(1);
// 			break;	
// 		}

// 		if(c[i]>='0' && c[i]<='9')	//as long as this is a digit
// 			num = num * 10 +c[i]-'0';//multiply by 10, add character ASCII-ASCII value for 0 (to get proper int value
// 		else	//if not a digit 
// 		{
// 			if(-1==write(1,"atoi failed: not an int\n",25))
// 				perror("write failed");exit(1);
// 			break;	
// 		}	
// 	}
// 	return num;
// }

